#ifndef __SYLAR_IOMANAGER_H__
#define __SYLAR_IOMANAGER_H__

#include "scheduler.h"
#include "timer.h"

namespace zsylar
{

// IOManager模块是一个基于epoll的IO事件调度器
// 工作流程
// 1 注册一个事件 -> 2 等待事件就绪 -> 3 调度回调函数 -> 4 注销事件 -> 5 执行回调函数
class IOManager : public Scheduler, public TimerManager
{
public:
    enum Event
    {
        NONE = 0X0,  // 无事件
        READ = 0X1,  // 读事件，对应 EPOLLIN
        WRITE = 0X4  // 写事件，对应 EPOLLOUT
    };

private:
    // 文件描述符上下文
    struct FdContext
    {
        // 事件上下文
        struct EventContext
        {
            Scheduler* scheduler = nullptr;  // 调度器
            std::shared_ptr<Fiber> fiber;    // 回调协程
            std::function<void()> cb;         // 回调函数
        };

        EventContext read;  // 读事件上下文
        EventContext write; // 写事件上下文
        int fd = 0;         // 文件描述符
        Event events = NONE; // 注册的事件
        std::mutex mutex;   // 互斥锁

        EventContext& getEventContext(Event event); // 获取事件上下文
        void resetEventContext(EventContext& ctx);   // 重置事件上下文
        void triggerEvent(Event event);              // 触发事件
    };

public:
    // 构造函数
    IOManager(size_t threads = 1, bool use_caller = true,
              const std::string& name = "IOManager");

    // 析构函数
    ~IOManager();

    // 添加一个事件
    int addEvent(int fd, Event event, std::function<void()> cb = nullptr);
    // 删除事件
    bool delEvent(int fd, Event event);
    // 删除事件并触发其回调
    bool cancelEvent(int fd, Event event);
    // 删除所有事件
    bool cancelAll(int fd);

protected:
    // 唤醒调度器
    virtual void tickle() override;
    // 判断是否停止
    bool stopping() override;
    // 空闲处理
    void idle() override;
    // 定时器插入到队列头部时的处理
    void onTimerInsertedAtFront() override;
    // 调整上下文大小
    void contextResize(size_t size);

private:
    int m_epfd = 0; // epoll文件描述符
    int m_tickleFds[2]; // 用于唤醒调度器的管道文件描述符 fd[0] 读，fd[1] 写
    std::atomic<size_t> m_pendingEventCount = {0}; // 待处理事件数量
    std::vector<FdContext*> m_fdContexts; // 文件描述符上下文列表
    std::shared_mutex m_mutex; // 共享锁，用于保护文件描述符上下stext列表
};

}

#endif